#include "stdafx.h"
#include "mShC.h"

struct shadowListener: public Ogre::SceneManager::Listener
{
    // this is a callback we'll be using to set up our shadow camera
    void shadowTextureCasterPreViewProj(Ogre::Light *light, Ogre::Camera *cam, size_t)
    {
        // basically, here we do some forceful camera near/far clip attenuation
        // yeah.  simplistic, but it works nicely.  this is the function I was talking
        // about you ignoring above in the Mgr declaration.
        float range = light->getAttenuationRange();
        cam->setNearClipDistance(0.1);
        cam->setFarClipDistance(200);
        // we just use a small near clip so that the light doesn't "miss" anything
        // that can shadow stuff.  and the far clip is equal to the lights' range.
        // (thus, if the light only covers 15 units of objects, it can only
        // shadow 15 units - the rest of it should be attenuated away, and not rendered)
    }

    // these are pure virtual but we don't need them...  so just make them empty
    // otherwise we get "cannot declare of type Mgr due to missing abstract
    // functions" and so on
    void shadowTexturesUpdated(size_t) {}
    void shadowTextureReceiverPreViewProj(Ogre::Light*, Ogre::Frustum*) {}
    void preFindVisibleObjects(Ogre::SceneManager*, Ogre::SceneManager::IlluminationRenderStage, Ogre::Viewport*) {}
    void postFindVisibleObjects(Ogre::SceneManager*, Ogre::SceneManager::IlluminationRenderStage, Ogre::Viewport*) {}
} shadowCameraUpdater;


void Application::setupScene()
    {
		
	   mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "mSceneMgr");
       Camera *cam = mSceneMgr->createCamera("Camera");
       Viewport *vp = mRoot->getAutoCreatedWindow()->addViewport(cam);
	   cam->setNearClipDistance(0.4);

	    m_World = NxOgre::World::createWorld();
	    m_World->getRemoteDebugger()->connect();
		m_World->setSkinWidth(0.01);
	    NxOgre::SceneDescription scene_description;
	    scene_description.mGravity = NxOgre::Vec3(0,-55,0);
	    scene_description.mUseHardware = false;
		//scene_description.mTimeStepMethod = NxOgre::Enums::TimeStepMethod_Variable;
	    m_Scene = m_World->createScene(scene_description);
		mRenderSystem = new Critter::RenderSystem(m_Scene, mSceneMgr);
	   cam->setFOVy(Degree(60));
	   cam->setAspectRatio(1.5);
	   cam->setPosition(Vector3(0,0,0));
	   cam->lookAt(Vector3(0,0,0));
		mSceneMgr->setAmbientLight(ColourValue(0.6, 0.6, 0.6));
		
		mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
		mSceneMgr->setShadowTextureCountPerLightType(Ogre::Light::LT_DIRECTIONAL, 3);
		mSceneMgr->setShadowTextureSettings(1024,3, PF_FLOAT32_R);
		mSceneMgr->setShadowTextureSelfShadow(true);
		mSceneMgr->setShadowTextureCasterMaterial("PSSM/shadow_caster");
		mSceneMgr->setShadowFarDistance(150);
		 //shadow camera setup
		PSSMShadowCameraSetup2* pssmSetup = new PSSMShadowCameraSetup2();
		pssmSetup->calculateSplitPoints(3,1,150);
		pssmSetup->setSplitPadding(2);
		//pssmSetup->setUseAggressiveFocusRegion(false);	
		//pssmSetup->setUseSimpleOptimalAdjust(false);		
		pssmSetup->setOptimalAdjustFactor(0, 0);
		pssmSetup->setOptimalAdjustFactor(1, 0);
		//pssmSetup->setOptimalAdjustFactor(2, 0);

		mSceneMgr->setShadowCasterRenderBackFaces(true);
		mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(pssmSetup));
		Ogre::PSSMShadowCameraSetup::SplitPointList splitPointList = pssmSetup->getSplitPoints();

		splitPointList[0]=1;
		splitPointList[1]=25;//25
		splitPointList[2]=70;//70
		splitPointList[3]=150;//150
		pssmSetup->setSplitPoints(splitPointList);

		//MaterialManager::getSingleton().setDefaultAnisotropy(4);
		MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_TRILINEAR);
		/*

	MaterialPtr mat = MaterialManager::getSingleton().getByName("01m");
	mat = MaterialManager::getSingleton().getByName("cubem");
	//mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
	mat = MaterialManager::getSingleton().getByName("domm");
	mat->getTechnique(0)->getPass(1)->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
    

//VSM
		/*
	mSceneMgr->setShadowTextureSelfShadow(true);
    mSceneMgr->setShadowTextureCasterMaterial("shadow_caster");
    mSceneMgr->setShadowTextureCount(1);
    mSceneMgr->setShadowTextureSize(512);
    mSceneMgr->setShadowTexturePixelFormat(Ogre::PF_FLOAT16_RGB);
    mSceneMgr->setShadowCasterRenderBackFaces(false);

    const unsigned numShadowRTTs = mSceneMgr->getShadowTextureCount();
    for (unsigned i = 0; i < numShadowRTTs; ++i)
    {
        Ogre::TexturePtr tex = mSceneMgr->getShadowTexture(i);
        Ogre::Viewport *vp = tex->getBuffer()->getRenderTarget()->getViewport(0);
        vp->setBackgroundColour(Ogre::ColourValue(1, 1, 1, 1));
        vp->setClearEveryFrame(true);
    }

	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
	 shadowListener* u=new  shadowListener();
    mSceneMgr->addListener(u);
	*/

		godRaysListener = new GodRaysListener();
		postProcessListener = new PostProcessListener();

		CompositorInstance *godRaysCompositor = CompositorManager::getSingleton().addCompositor(cam->getViewport(), "GodRays");
		godRaysCompositor->addListener(godRaysListener);
		CompositorManager::getSingleton().setCompositorEnabled(cam->getViewport(), "GodRays",true);

	    CompositorInstance *bloomCompositor = Ogre::CompositorManager::getSingleton().addCompositor(cam->getViewport(), "Bloom");
		bloomCompositor->addListener(postProcessListener);
		Ogre::CompositorManager::getSingleton().setCompositorEnabled(cam->getViewport(), "Bloom", true);

	//	Ogre::CompositorManager::getSingleton().addCompositor(cam->getViewport(), "MyDof");
	//	Ogre::CompositorManager::getSingleton().setCompositorEnabled(cam->getViewport(), "MyDof", true);
		

    }